package com.netty.test.controller;

import cn.hserver.plugin.web.annotation.Controller;
import cn.hserver.plugin.web.annotation.RequestMapping;
import cn.hserver.plugin.web.interfaces.HttpRequest;
import cn.hserver.plugin.web.interfaces.HttpResponse;
import com.netty.test.service.BackendHandler;
import com.netty.test.util.HttpsMapperSslContextFactory;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.ssl.SslHandler;

import javax.net.ssl.SSLEngine;

/**
 * @author hxm
 */
@Controller
public class ProxyController {


    //这里的例子是代理百度，用了ssl 如果是内网的话就不用ssl了，代理有的服务有验证host 请灵活处理这个字段
    @RequestMapping("/proxy")
    public void proxy(HttpRequest request, HttpResponse response) {
        response.isProxy(true);
        ChannelHandlerContext ctx = request.getCtx();
        FullHttpRequest msg = request.getNettyRequest();
        msg.setUri("/s?ie=UTF-8&wd=test");
        msg.headers().set("host", "www.baidu.com");
        //此处的OutboundChannel是绑定在handler上的请不要自己定义
        if (request.getOutboundChannel() == null || !ctx.channel().isActive()) {
            Bootstrap bootstrap = new Bootstrap();
            SSLEngine sslEngine = HttpsMapperSslContextFactory.getClientContext().createSSLEngine();
            sslEngine.setUseClientMode(true);
            bootstrap.group(ctx.channel().eventLoop())
                    .channel(ctx.channel().getClass())
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch)
                                throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            //如果是https 就打开
                            pipeline.addFirst(new SslHandler(sslEngine));
                            pipeline.addLast(new HttpClientCodec());
                            pipeline.addLast(new HttpObjectAggregator(1048576));
                            pipeline.addLast(new BackendHandler(ctx.channel()));
                        }
                    });
            ChannelFuture future = bootstrap.connect("www.baidu.com", 443);
            //此处的OutboundChannel是绑定在handler上的请不要自己定义
            request.setOutboundChannel(future.channel());
            future.addListener((ChannelFutureListener) future1 -> {
                if (future1.isSuccess()) {
                    future1.channel().writeAndFlush(msg);
                } else {
                    future1.channel().close();
                }
            });
        } else {
            //复用操作
            //此处的OutboundChannel是绑定在handler上的请不要自己定义
            request.getOutboundChannel().writeAndFlush(msg);
        }
    }
}
